package main.bio;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: XJL
 * @Description:
 *
 * 当客户端连接上了服务端之后，accept的堵塞状态才会放开，然后进入read环节（读取客户端发送过来的网络数据）。
 * 这段代码当中的主要关注点在于accept函数和read函数，因为传统的bio技术会在这两个模块中发生堵塞情况。
 *
 * 服务端创建了socket之后会堵塞在等待外界连接的accept函数环节，大概流程我整理了图BioServer.png所示,
 *
 * 当客户端连接上了服务端之后，accept的堵塞状态才会放开，然后进入read环节（读取客户端发送过来的网络数据）。
 * 客户端如果一直没有发送数据过来，那么服务端的read调用方法就会一直处于堵塞状态，倘若数据通过网络抵达了网卡缓冲区，
 * 此时则会将数据从内核态拷贝至用户态，然后返回给read调用方。
 * @Date: Create in 22:06 2022-04-19
 * @Modified By:
 **/
public class BioServer {

    private static ExecutorService executors = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress(1009));

        try {
            while (true) {
                //堵塞状态点--1

                Socket socket = serverSocket.accept();
                System.out.println("获取新连接");

                executors.execute(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            InputStream inputStream = null;

                            try {
                                //堵塞的状态点--2
                                inputStream = socket.getInputStream();
                                byte[] result = new byte[1024];

                                int len = inputStream.read(result);
                                if (len != -1) {
                                    System.out.println("[response] "+new String(result,0,len));

                                    OutputStream outputStream = socket.getOutputStream();
                                    outputStream.write("response data".getBytes());
                                    outputStream.flush();

                                }

                            } catch (Exception e) {
                                e.printStackTrace();
                                break;
                            }
                        }
                    }
                });
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
